import unittest
from FWIFunctions import *

def suite():
    '''Compiles all unit tests into a single test suite'''

    #Some of the tests depend upon the success of earlier tests to succeed
    testFWI = [
            'testExample',
            'testLawsonEq1',
            'testLawsonEq2',
            'testLawsonEq3',
            'testLawsonEq4',
            'testLawsonEq5',
        ]
    return unittest.TestSuite(
                map(TestFWIFunctions,testFWI)
            )

class TestFWIFunctions(unittest.TestCase):
    '''Unittest for FWIFunctions.py'''

    def setUp(self):
        self.MC =  [[301, 235, 400, 400, 400],
                    [270, 210, 400, 400, 400],
                    [243, 189, 400, 400, 400],
                    [219, 170, 345, 400, 400],
                    [197, 153, 285, 357, 400],
                    [178, 138, 237, 261, 388],
                    [161, 125, 197, 192, 306],
                    [145, 113, 164, 143, 241],
                    [132, 102, 138, 108, 189],
                    [120,  93, 116,  83, 149],
                    [109,  85,  98,  65, 117],
                    [99,   77,  84,  52,  92],
                    [91,   71,  72,  43,  73],
                    [83,   65,  63,  36,  57],
                    [76,   60,  55,  32,  45],
                    [70,   56,  48,  28,  35],
                    [64,   52,  43,  26,  28],
                    [60,   48,  39,  24,  22],
                    [55,   45,  35,  23,  17],
                    [51,   42,  33,  22,  14],
                    [48,   40,  30,  22,  11],
                    [45,   37,  28,  21,  11],
                    [42,   35,  27,  21,  11],
                    [40,   34,  26,  21,  11],
                    [38,   32,  25,  20,  11],
                    [36,   31,  24,  20,  11],
                    [34,   30,  23,  20,  11],
                    [33,   28,  22,  20,  11],
                    [31,   27,  22,  20,  11]]

    def testExample(self):
        '''Compare output to results from FWI_Examples.xls'''

        inputs = [[4,13,17,42,25,0],
                  [4,14,20,21,25,2.4],
                  [4,15,8.5,40,17,1],
                  [4,16,6.5,25,6,2],
                  [4,17,13,34,24,0.5],
                  [4,18,6,40,22,0.4],
                  [4,19,5.5,52,6,0],
                  [4,20,8.5,46,16,0],
                  [4,21,9.5,54,20,0],
                  [4,22,7,93,14,9],
                  [4,23,6.5,71,17,5],
                  [4,24,6,59,17,0],
                  [4,25,13,52,4,0],
                  [4,26,15.5,40,11,0],
                  [4,27,23,25,9,0],
                  [4,28,19,46,16,0],
                  [4,29,18,41,20,0],
                  [4,30,14.5,51,16,0],
                  [5,1,14.5,69,11,0],
                  [5,2,15.5,42,8,0],
                  [5,3,21,37,8,0],
                  [5,4,23,32,16,0],
                  [5,5,23,32,14,0],
                  [5,6,27,33,12,0],
                  [5,7,28,17,27,0],
                  [5,8,23.5,54,20,0],
                  [5,9,16,50,22,12.2],
                  [5,10,11.5,58,20,0],
                  [5,11,16,54,16,0],
                  [5,12,21.5,37,9,0],
                  [5,13,14,61,22,0.2],
                  [5,14,15,30,27,0],
                  [5,15,20,23,11,0],
                  [5,16,14,95,3,16.4],
                  [5,17,20,53,4,2.8],
                  [5,18,19.5,30,16,0],
                  [5,19,25.5,51,20,6],
                  [5,20,10,38,24,0],
                  [5,21,19,27,16,0],
                  [5,22,26,46,11,4.2],
                  [5,23,30,38,22,0],
                  [5,24,25.5,67,19,12.6],
                  [5,25,12,53,28,11.8],
                  [5,26,21,38,8,0],
                  [5,27,13,70,20,3.8],
                  [5,28,9,78,24,1.4],
                  [5,29,11,54,16,0],
                  [5,30,15.5,39,9,0],
                  [5,31,18,36,5,0]]

        #50*6
        outputs = [[85,6,15,0.0,0.0,0.0],
                   [87.6929800927744,8.5450511360000,19.0140000000000,10.8536610736551,8.4904265358372,10.0963713923824],
                   [86.2476421959384,10.4110880971949,23.5680000000000,8.8375743849078,10.3641362097039,9.2838792845466],
                   [83.0071652463898,11.8074964171949,26.0520000000000,3.8064787583966,11.7480399563820,4.4907198972308],
                   [73.9238099555348,11.3825854102869,28.1760000000000,0.9810905126658,11.3778753807330,0.6353923825346],
                   [85.4711980360439,13.6386576022869,31.4700000000000,7.5375402599695,13.6001091271186,9.2396225234188],
                   [86.4260976866327,14.6714179222869,33.5040000000000,7.7914842650420,14.6276401732900,9.8529079027888],
                   [86.3328990295461,15.4394424982869,35.4480000000000,3.4336653050609,15.3980777189720,4.7531136450242],
                   [86.3810458115297,16.6962099862869,37.9320000000000,5.7220447857230,16.6493832921113,8.0783196608168],
                   [86.4292084891899,17.8783084182869,40.5960000000000,7.0476274884329,17.8308685222509,10.0152125603295],
                   [29.7767243103294,9.2208590988493,29.5246951034065,0.0065618926869,10.3560061321656,0.0040344155532],
                   [36.8643333868907,5.7125634359183,25.5912236051709,0.0433237107157,7.3329238728194,0.0222575511972],
                   [59.8225367490447,6.4182829879183,27.6252236051709,0.9533553930546,8.1201155248162,0.5155077017868],
                   [74.1552421670152,8.0590627639183,30.9192236051709,0.8969081926930,9.7589655421646,0.5339908280774],
                   [84.3838840628007,10.4736854839183,34.6632236051709,3.3726660784328,11.9331797005687,3.9783189368617],
                   [91.3274500869143,14.8556438839183,39.7572236051709,8.1552799395198,15.3614387118449,10.4865808588410],
                   [89.8893582094977,17.4870008119183,44.1312236051709,9.4501766225832,17.5693554445234,12.6229948595425],
                   [89.9386791577078,20.2189670199183,48.3252236051709,11.6424855802443,20.1964351964434,15.8709337015900],
                   [88.4212875939822,22.0721172279183,51.8892236051709,7.6550641550336,22.0408945107400,11.9546824922680],
                   [85.7015237817855,23.3452716039183,56.9032236051709,4.0427104561672,23.3322844708395,7.1558518587256],
                   [87.3844212717517,25.8799966519183,62.0972236051709,4.4095385832985,25.8585348671966,8.2121111233157],
                   [89.3859697618029,29.5454491699183,68.2812236051709,5.8750768382668,29.5031430108232,11.2668369998561],
                   [90.9843790560489,33.8598523779183,74.8252236051709,11.0514683938624,33.7909631656374,19.6308068874416],
                   [91.2052984177865,38.1742555859183,81.3692236051709,10.3113180819856,38.0817221664868,19.8153171845857],
                   [91.6578858808443,43.1307645679183,88.6332236051709,9.9418505145734,43.0116573607316,20.5215488726052],
                   [95.1657450507055,49.4894282659183,96.0772236051709,34.5221396993449,49.3261760093888,50.3651223652541],
                   [89.7012137527159,52.4685463219183,102.7112236051710,11.2528579323146,52.3058023506295,24.7235116353810],
                   [62.2306851415413,27.5516710000547,86.0705197975802,1.4087542482347,30.6084708214731,2.8328053607645],
                   [76.6951238007001,28.9448746720547,90.5445197975802,2.3335215856650,32.1754682105837,5.1897682231417],
                   [83.4505611054897,31.0157250280547,95.8285197975802,3.8329201250586,34.2876873903939,8.5727672801307],
                   [88.6705288621372,34.7641063360547,102.1025197975800,5.5756473671225,37.5583359977095,12.3318413769731],
                   [86.6749802807784,36.3144798100547,107.0265197975800,8.0708908952793,39.2958795130755,16.8097882367398],
                   [89.6322419368960,39.2814876300547,112.1305197975800,15.8546187997933,41.8824215209747,28.1016483873038],
                   [92.1267841247568,43.5587703320547,118.1345197975800,10.1019156199212,45.3311161537364,21.3175451570346],
                   [21.3333089165973,18.9273412744807,91.6796049803422,0.0002510480618,24.9680095198720,0.0002624435337],
                   [51.0377326927863,17.2748043416307,97.6836049803422,0.2269855493064,23.9576600616842,0.2309821908904],
                   [82.2651203733947,21.0711000616307,103.5976049803420,3.2973855509147,27.9367850267685,6.6133578725000],
                   [75.3587099900044,15.7965113651198,101.2396537824160,2.1415071178829,22.7275314194089,3.7059586223383],
                   [84.3233243710070,17.6083079771198,105.4436537824160,6.4404716912564,24.8444985603667,11.0672316317503],
                   [90.3073973037607,21.4712099951198,111.2676537824160,10.0331302696660,28.9677326237168,16.9307090391965],
                   [77.5781637114086,18.2717015197370,112.6315549109900,1.5843026140325,25.9991111131650,2.8647200220462],
                   [90.2152156400837,23.3479965317370,120.4355549109900,13.3971548482646,31.4523679772226,21.7722395919584],
                   [65.3166611011500,12.9907658475620,103.7062403064070,1.3910843896421,19.7854644429467,1.8294142505778],
                   [55.4161969758836,7.6795449563813,87.0949022139026,1.1877254013983,12.5849191532490,0.8144036856768],
                   [80.8439685275063,11.2868156883813,93.2789022139026,1.8641740114048,17.3309785408324,2.5235701417712],
                   [61.7412874398901,8.3720402746502,93.3674395771310,1.2412418528281,13.6779140246919,0.8931163585945],
                   [64.4820340804801,8.9570173266502,97.3914395771310,1.7303747168032,14.5651662381855,1.9283071116642],
                   [77.6339623122620,10.4223558826502,101.7754395771310,2.0473552904203,16.5959292972917,2.7615259423299],
                   [85.4302471154276,13.0881873986502,106.9694395771310,3.5196326372219,20.0449136293347,5.7332862706794],
                   [88.4592189214233,16.3063509826502,112.6134395771310,4.4216825593812,23.9447443973691,7.8745783992324]]

        results = [[0 for x in range(0,6)] for y in range(0,50)]

        results[0] = outputs[0]

        #process each line at a time
        for x in range(0,49):
            try:
                ffmc = FFMC(inputs[x][2],inputs[x][3],inputs[x][4],inputs[x][5],results[x][0])
                dmc = DMC(inputs[x][2],inputs[x][3],inputs[x][5],results[x][1],45.98,inputs[x][0])
                print inputs[x][2],inputs[x][3],inputs[x][5],results[x][1],45.98,inputs[x][0],dmc
                dc = DC(inputs[x][2],inputs[x][5],results[x][2],45.98,inputs[x][0])
                isi = ISI(inputs[x][4], ffmc)
                bui = BUI(dmc,dc)
                fwi = FWI(isi, bui)

                results[x+1] = [ffmc,dmc,dc,isi,bui,fwi]

                final = True

                #compare each variable to the result from the excel version
                for t in range(0,6):
                    final = final & self.nearlyEqual(results[x+1][t],outputs[x+1][t])

                #custom error message
                if not(final):
                    print "Failed on line " + repr(x) + ":"
                    print "Inputs: " + repr(inputs[x])
                    print "Expected: " + repr(outputs[x+1])
                    print "Got: " + repr(results[x+1])
            
                self.assertTrue(final)
            except:
                print "Error on line " + repr(x+1) + ":"
                print "Inputs: " + repr(inputs[x])
                raise

    def testLawsonEq1(self):
        DMC = range(0,145,5)

        for d in DMC:
            self.assertEqual(min(int(LawsonEq1(d)+.5),400),self.MC[d/5][0])

    def testLawsonEq2(self):
        DMC = range(0,145,5)

        for d in DMC:
            self.assertEqual(min(int(LawsonEq2(d)+.5),400),self.MC[d/5][1])

    def testLawsonEq3(self):
        DMC = range(0,145,5)

        for d in DMC:
            self.assertEqual(min(int(LawsonEq3(d)+.5),400),self.MC[d/5][2])

    def testLawsonEq4(self):
        DMC = range(0,145,5)

        for d in DMC:
            self.assertEqual(min(int(LawsonEq4(d)+.5),400),self.MC[d/5][3])

    def testLawsonEq5(self):
        DMC = range(0,145,5)

        for d in DMC:
            self.assertEqual(max(min(int(LawsonEq5(d)+.5),400),11),self.MC[d/5][4])




    def nearlyEqual(self, a, b):
        '''usefull for comparing doubles that may not be identical but are close enough'''
        if abs(a-b) < 5*pow(10,-10):
            return True
        return False

if __name__ == '__main__':
    unittest.TextTestRunner(verbosity=2).run(suite())


